package com.gobang.common.util;

import com.gobang.domain.message.MatchStatusUpdateMessage;
import com.gobang.domain.message.MatchSuccessMessage;
import com.gobang.domain.entity.MatchQueueEntry;
import com.gobang.domain.vo.MatchSuccessNotificationVO;
import com.gobang.service.MatchService;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;

/**
 * 匹配相关工具类
 * 提供匹配系统的辅助功能和计算方法
 *
 * @author gobang-team
 * @since 1.0.0
 */
public class MatchUtils {

    private static final Random RANDOM = new Random();
    
    // 匹配算法相关常量
    public static final int BASE_MATCH_THRESHOLD = 100; // 基础匹配阈值（积分差）
    public static final double THRESHOLD_EXPAND_FACTOR = 2.0; // 阈值扩展因子（每秒）
    public static final long MAX_WAIT_TIME = 300; // 最大等待时间（秒）
    public static final int ESTIMATED_WAIT_BASE = 15; // 基础预估等待时间（秒）
    
    // 房间ID生成相关常量
    private static final String ROOM_ID_PREFIX = "room_";
    private static final DateTimeFormatter ROOM_ID_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    /**
     * 生成房间ID
     * 格式：room_{timestamp}_{random}
     *
     * @return 房间ID
     */
    public static String generateRoomId() {
        String timestamp = LocalDateTime.now().format(ROOM_ID_TIME_FORMAT);
        int randomSuffix = RANDOM.nextInt(1000);
        return String.format("%s%s_%03d", ROOM_ID_PREFIX, timestamp, randomSuffix);
    }

    /**
     * 随机分配玩家颜色
     *
     * @return 玩家颜色 "BLACK" 或 "WHITE"
     */
    public static String randomPlayerColor() {
        return RANDOM.nextBoolean() ? "BLACK" : "WHITE";
    }

    /**
     * 获取对手颜色
     *
     * @param playerColor 玩家颜色
     * @return 对手颜色
     */
    public static String getOpponentColor(String playerColor) {
        return "BLACK".equals(playerColor) ? "WHITE" : "BLACK";
    }

    /**
     * 计算积分差值
     *
     * @param score1 用户1积分
     * @param score2 用户2积分
     * @return 积分差值的绝对值
     */
    public static int calculateScoreDifference(int score1, int score2) {
        return Math.abs(score1 - score2);
    }

    /**
     * 计算动态匹配阈值
     * 根据等待时间动态放宽匹配条件
     *
     * @param waitTime 等待时间（秒）
     * @return 动态匹配阈值
     */
    public static int calculateDynamicThreshold(long waitTime) {
        // 动态阈值 = 基础阈值（100）+ [等待时间 * 阈值扩展因子（2.0）]
        // 等待时间越长，动态阈值越大
        // 希望用户等待时间越长，匹配优先级越高？
        return (int) (BASE_MATCH_THRESHOLD + (waitTime * THRESHOLD_EXPAND_FACTOR));
    }

    /**
     * 计算预估等待时间
     * 根据队列位置预估等待时间
     *
     * @param queuePosition 队列位置
     * @return 预估等待时间（秒）
     */
    public static long calculateEstimatedWaitTime(int queuePosition) {
        // 简单的线性预估：基础时间 + (位置-1) * 每位置额外时间
        return ESTIMATED_WAIT_BASE + (long) (queuePosition - 1) * 10;
    }

    /**
     * 检查是否超过最大等待时间
     *
     * @param waitTime 等待时间（秒）
     * @return 是否超时
     */
    public static boolean isWaitTimeExceeded(long waitTime) {
        return waitTime > MAX_WAIT_TIME;
    }

    /**
     * 创建匹配状态更新消息
     *
     * @param status 匹配状态
     * @param waitTime 等待时间
     * @param queuePosition 队列位置
     * @return 匹配状态更新消息
     */
    public static MatchStatusUpdateMessage createMatchStatusUpdateMessage(String status, Integer waitTime, Integer queuePosition) {
        MatchStatusUpdateMessage.MatchStatusUpdateData data = MatchStatusUpdateMessage.MatchStatusUpdateData.builder()
                .status(status)
                .waitTime(waitTime)
                .queuePosition(queuePosition)
                .build();
        return new MatchStatusUpdateMessage(data);
    }

    /**
     * 创建匹配成功消息
     *
     * @param roomId 房间ID
     * @param opponent 对手信息
     * @param playerColor 玩家颜色
     * @param startTime 开始时间
     * @return 匹配成功消息
     */
    public static MatchSuccessMessage createMatchSuccessMessage(String roomId, 
                                                               MatchService.MatchOpponentInfo opponent, 
                                                               String playerColor, 
                                                               String startTime) {
        MatchSuccessMessage.MatchSuccessData data = MatchSuccessMessage.MatchSuccessData.builder()
                .roomId(roomId)
                .opponent(MatchSuccessMessage.OpponentInfo.builder()
                        .id(opponent.getId())
                        .username(opponent.getUsername())
                        .currentScore(opponent.getCurrentScore())
                        .build())
                .playerColor(playerColor)
                .startTime(startTime)
                .build();
        return new MatchSuccessMessage(data);
    }

    /**
     * 转换为匹配成功通知VO
     *
     * @param roomId 房间ID
     * @param opponent 对手信息
     * @param playerColor 玩家颜色
     * @param startTime 开始时间
     * @return 匹配成功通知VO
     */
    public static MatchSuccessNotificationVO createMatchSuccessNotificationVO(String roomId,
                                                                              MatchService.MatchOpponentInfo opponent,
                                                                              String playerColor,
                                                                              LocalDateTime startTime) {
        return MatchSuccessNotificationVO.builder()
                .roomId(roomId)
                .opponent(MatchSuccessNotificationVO.OpponentInfo.builder()
                        .id(opponent.getId())
                        .username(opponent.getUsername())
                        .currentScore(opponent.getCurrentScore())
                        .build())
                .playerColor(playerColor)
                .startTime(startTime)
                .build();
    }

    /**
     * 验证用户是否可以匹配
     * 检查用户状态是否允许进行匹配
     *
     * @param userStatus 用户状态
     * @return 是否可以匹配
     */
    public static boolean canUserMatch(String userStatus) {
        return "online".equals(userStatus);
    }

    /**
     * 验证队列条目是否有效
     *
     * @param entry 队列条目
     * @return 是否有效
     */
    public static boolean isValidQueueEntry(MatchQueueEntry entry) {
        return entry != null 
                && entry.getUserId() != null 
                && entry.getCurrentScore() != null 
                && entry.getJoinTime() != null;
    }

    /**
     * 生成匹配状态描述消息
     *
     * @param status 匹配状态
     * @param queuePosition 队列位置
     * @param waitTime 等待时间
     * @return 状态描述
     */
    public static String generateStatusMessage(String status, Integer queuePosition, Integer waitTime) {
        switch (status) {
            case "MATCHING":
                return String.format("正在匹配中，队列位置：%d，已等待：%d秒", queuePosition, waitTime);
            case "MATCHED":
                return "匹配成功，准备进入游戏";
            case "ONLINE":
                return "在线状态，可以开始匹配";
            default:
                return "未知状态";
        }
    }
} 